package com.example.video_demo;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Package: com.example.video_demo
 * Date:    10/23/21
 * Desc:    com.example.video_demo
 *
 * @author liujicheng
 */
public class Utils {
    public static class RGB {
        int r = 0;
        int g = 0;
        int b = 0;
    }

    /**
     * RGB图片转YUV420数据  NV21
     * <p>
     * 宽、高不能为奇数
     *
     * @param pixels 图片像素集合
     * @param width  宽
     * @param height 高
     * @return
     */
    public static byte[] rgb2YCbCr420(int[] pixels, int width, int height) {
        int len = width * height;
        //yuv格式数组大小，y亮度占len长度，u,v各占len/4长度。
        byte[] yuv = new byte[len * 3 / 2];
        int y, u, v;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                //屏蔽ARGB的透明度值
                int rgb = pixels[i * width + j] & 0x00FFFFFF;
                //像素的颜色顺序为bgr，移位运算。
                int r = rgb & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = (rgb >> 16) & 0xFF;
                //套用公式
                y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
                u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
                v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;

                //调整
                y = y < 16 ? 16 : (y > 255 ? 255 : y);
                u = u < 0 ? 0 : (u > 255 ? 255 : u);
                v = v < 0 ? 0 : (v > 255 ? 255 : v);
                //赋值
                yuv[i * width + j] = (byte) y;
                yuv[len + (i >> 1) * width + (j & ~1)] = (byte) u;
                yuv[len + +(i >> 1) * width + (j & ~1) + 1] = (byte) v;


            }
        }
        return yuv;
    }

    public static RGB yuvToRgb(byte Y, byte U, byte V) {
        RGB rgb = new RGB();
        rgb.r = (int) ((Y & 0xff) + 1.4075 * ((V & 0xff) - 128));
        rgb.g = (int) ((Y & 0xff) - 0.3455 * ((U & 0xff) - 128) - 0.7169 * ((V & 0xff) - 128));
        rgb.b = (int) ((Y & 0xff) + 1.779 * ((U & 0xff) - 128));
        rgb.r = (rgb.r < 0 ? 0 : rgb.r > 255 ? 255 : rgb.r);
        rgb.g = (rgb.g < 0 ? 0 : rgb.g > 255 ? 255 : rgb.g);
        rgb.b = (rgb.b < 0 ? 0 : rgb.b > 255 ? 255 : rgb.b);
        return rgb;
    }

    public static Bitmap yuvToBitMap(byte[] data, int width, int height) {
        YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null);
        Bitmap bmp = null;
        if (image != null) {
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            image.compressToJpeg(new Rect(0, 0, width, height), 100, stream);

            bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());

            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return bmp;
    }

    /**
     * @方法描述 将RGB字节数组转换成Bitmap，
     */
    public static Bitmap rgb2Bitmap(byte[] data, int width, int height) {
        int[] colors = convertByteToColor(data); //取RGB值转换为int数组
        return Bitmap.createBitmap(colors, 0, width, width, height,
                Bitmap.Config.ARGB_8888);
    }

    // 将纯RGB数据数组转化成int像素数组
    public static int[] convertByteToColor(byte[] data) {
        int size = data.length;
        if (size == 0) {
            return null;
        }
        int arg = 0;
        if (size % 3 != 0) {
            arg = 1;
        }

        // 一般RGB字节数组的长度应该是3的倍数，
        // 不排除有特殊情况，多余的RGB数据用黑色0XFF000000填充
        int[] color = new int[size / 3 + arg];
        int red;
        int green;
        int blue;
        int colorLen = color.length;
        if (arg == 0) {
            for (int i = 0; i < colorLen; i++) {
                red = convertByteToInt(data[i * 3]);
                green = convertByteToInt(data[i * 3 + 1]);
                blue = convertByteToInt(data[i * 3 + 2]);

                // 获取RGB分量值通过按位或生成int的像素值
                color[i] = red << 16 | (green << 8) | blue | -0x1000000;
            }
        } else {
            for (int i = 0; i < colorLen; i++) {
                red = convertByteToInt(data[i * 3]);
                green = convertByteToInt(data[i * 3 + 1]);
                blue = convertByteToInt(data[i * 3 + 2]);
                color[i] = red << 16 | (green << 8) | blue | -0x1000000;
            }
            color[colorLen - 1] = -0x1000000;
        }
        return color;
    }

    // 将一个byte数转成int
    // 实现这个函数的目的是为了将byte数当成无符号的变量去转化成int
    public static int convertByteToInt(byte data) {
        int heightBit = ((data >>> 4) & 0x0F);
        return heightBit * 16 + (0x0F & data);
    }

    public static boolean writeFile(String path, byte[] data) {
        FileOutputStream out = null;
        try {
            File file = new File(path);
            File parent = file.getParentFile();
            if (parent != null && !parent.exists())
                parent.mkdirs();
//            if (!file.exists()) {
            boolean isok = file.createNewFile();
            out = new FileOutputStream(path);
            out.write(data);
            FileDescriptor fd = out.getFD();
            fd.sync();
            return true;
//            }
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (Exception e) {
            }
        }
        return false;
    }
}
